package com.lwww.infinitechat.authenticationservice.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lwww.infinitechat.authenticationservice.constants.config.OSSConstants;
import com.lwww.infinitechat.authenticationservice.constants.user.ErrorEnum;
import com.lwww.infinitechat.authenticationservice.data.user.login.LoginRequest;
import com.lwww.infinitechat.authenticationservice.data.user.login.LoginResponse;
import com.lwww.infinitechat.authenticationservice.data.common.upload.UploadUrlRequest;
import com.lwww.infinitechat.authenticationservice.data.common.upload.UploadUrlResponse;
import com.lwww.infinitechat.authenticationservice.data.user.updateAvatar.UpdateAvatarRequest;
import com.lwww.infinitechat.authenticationservice.data.user.updateAvatar.UpdateAvatarResponse;
import com.lwww.infinitechat.authenticationservice.exception.CodeException;
import com.lwww.infinitechat.authenticationservice.utils.JwtUtil;
import com.lwww.infinitechat.authenticationservice.utils.NickNameGeneraterUtil;
import com.lwww.infinitechat.authenticationservice.constants.user.RegisterConstant;
import com.lwww.infinitechat.authenticationservice.data.user.register.RegisterRequest;
import com.lwww.infinitechat.authenticationservice.data.user.register.RegisterResponse;
import com.lwww.infinitechat.authenticationservice.exception.DataBaseException;
import com.lwww.infinitechat.authenticationservice.exception.UserException;
import com.lwww.infinitechat.authenticationservice.mapper.UserMapper;
import com.lwww.infinitechat.authenticationservice.model.User;
import com.lwww.infinitechat.authenticationservice.service.UserService;
import com.lwww.infinitechat.authenticationservice.utils.OSSUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OSSUtils ossUtils;

    /**
     * 用户注册
     * @param request
     * @return
     */
    public RegisterResponse register(RegisterRequest request) {
        String phone = request.getPhone();
        String password = request.getPassword();

        //先去数据库查是否有这个用户
        //存在就抛异常---->用户已存在
        if(isExist(phone)){
            throw new UserException(ErrorEnum.REGISTER_ERROR);
        }

        //不存在就注册---->redis里比对验证码
        String redisCode = redisTemplate.opsForValue().get(RegisterConstant.REGISTER_CODE + phone);
        if(redisCode==null || !redisCode.equals(request.getCode())){
            throw new UserException(ErrorEnum.REGISTER_CODE_ERROR);
        }

        //验证码正确就去数据库插入用户,错误就返回错误信息
        //生成唯一的用户ID----->雪花算法
        Snowflake snowflake = IdUtil.getSnowflake(1, 1);
        //将password转换成密文
        String encryptedPassword = DigestUtils.md5DigestAsHex(password.getBytes());
        //snowflake.nextId()------>生成最终的64位Long型ID
        User user =new User().setUserId(snowflake.nextId())
                .setPhone(phone)
                .setPassword(encryptedPassword)
                .setUserName(NickNameGeneraterUtil.generateName());
        if(!this.save(user)){
            throw new DataBaseException(ErrorEnum.SAVE_USER_ERROR);
        }
        return new RegisterResponse().setPhone(phone);
    }

    /**
     * 用户密码登录
     * @param request
     * @return
     */
    public LoginResponse loginByPassword(LoginRequest request) {
        String phone = request.getPhone();
        String password = request.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",phone);
        User user = this.getOnlyUser(wrapper,true);
        if(user==null||!password.equals(user.getPassword())){
            throw new UserException(ErrorEnum.LOGIN_ERROR);
        }

        LoginResponse response = new LoginResponse();
        BeanUtils.copyProperties(user,response);
        String jwt = JwtUtil.generateJwt(user.getUserId().toString());
        response.setToken(jwt);
        return response;
    }

    /**
     * 用户验证码登录
     * @param request
     * @return
     */
    public LoginResponse loginByCode(LoginRequest request) {
        String phone = request.getPhone();
        String code = request.getCode();
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",phone);
        User user = this.getOnlyUser(wrapper,true);
        //redis比对验证码
        String redisCode = redisTemplate.opsForValue().get(RegisterConstant.REGISTER_CODE + phone);
        //检查用户是否存在
        if (user==null||redisCode==null || !redisCode.equals(code)){
            throw new CodeException(ErrorEnum.LOGIN_CODE_ERROR);
        }

        LoginResponse response = new LoginResponse();
        BeanUtils.copyProperties(user,response);
        String jwt = JwtUtil.generateJwt(user.getUserId().toString());
        response.setToken(jwt);
        return response;
    }

    /**
     * 用户退出 todo
     * @param userId
     */
    public void logout(String userId) {

    }

    /**
     * 用户获取OSS预授权上传链接
     * @param request
     * @return
     */
    public UploadUrlResponse uploadUrl(UploadUrlRequest request) throws Exception {
        String fileName = request.getFileName();
        String uploadUrl = ossUtils.uploadUrl(OSSConstants.BUCKET_NAME, fileName, OSSConstants.PICTURE_EXPIRES_TIME);
        String downloadUrl = ossUtils.downloadUrl(OSSConstants.BUCKET_NAME, fileName);

        return new UploadUrlResponse().setUploadUrl(uploadUrl).setDownloadUrl(downloadUrl);
    }

    /**
     * 更新用户头像
     * @param userId
     * @param
     */
    public UpdateAvatarResponse updateAvatar(UpdateAvatarRequest request, String userId) {
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.eq("user_id",Long.valueOf(userId));
        User user = this.getOnlyUser(wrapper, true);
        if(user==null){
            throw new UserException(ErrorEnum.NO_USER_ERROR);
        }
        user.setAvatar(request.getAvatarUrl());
        boolean update = this.updateById(user);
        if(!update){
            throw new DataBaseException(ErrorEnum.UPDATE_AVATAR_ERROR);
        }
        UpdateAvatarResponse response = new UpdateAvatarResponse();
        BeanUtils.copyProperties(user,response);
        return response;
    }

    /**
     * 查询用户是否存在
     * @param phone
     * @return
     */
    private boolean isExist(String phone){
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.eq("phone",phone);
        long count = this.count(wrapper);
        return count>0;
    }
}
